//const int N = 1e5 + 10;
//int arr[N];
//int n;
//
//int main()
//{
//    cin >> n;
//    for (int i = 0; i < n; i++)
//        cin >> arr[i];
//
//    int ret = 0, i = 0;
//    while (i < n)
//    {
//        if (i == n - 1)
//        {
//            ret++;
//            break;
//        }
//
//
//        if (arr[i] > arr[i + 1])
//        {
//            ret++;
//            while (i + 1 < n && arr[i] >= arr[i + 1])
//                i++;
//        }
//        else if (arr[i] < arr[i + 1])
//        {
//            ret++;
//            while (i + 1 < n && arr[i] <= arr[i + 1])
//                i++;
//        }
//        else
//        {
//            while (i + 1 < n && arr[i] == arr[i + 1])
//                i++;
//        }
//        i++;
//    }
//    cout << ret << endl;
//    return 0;
//}


//int T, H;
//
//int func()
//{
//    int ret = 0, a = 1;
//    while (H)
//    {
//        H -= a; ret++;
//        if (H % (a * 2) == 0)
//        {
//            a *= 2;
//        }
//    }
//    return ret;
//}
//
//int main()
//{
//    cin >> T;
//    while (T--)
//    {
//        cin >> H;
//        cout << func() << endl;
//    }
//    return 0;
//}



//int LIS(vector<int>& a) {
//    int ret = 1, n = a.size();
//    if (n == 0) return 0;
//    vector<int> dp(n, 1);
//    for (int i = 1; i < n; i++)
//    {
//        for (int j = i - 1; j >= 0; j--)
//        {
//            if (a[i] > a[j])
//                dp[i] = max(dp[i], dp[j] + 1);
//        }
//        ret = max(ret, dp[i]);
//    }
//    return ret;
//}




//class Solution
//{
//	int dp[100010] = { 0 };
//	int pos = 0;
//public:
//	int LIS(vector<int>& a)
//	{
//		for (auto x : a)
//		{
//			if (pos == 0 || x > dp[pos])
//			{
//				dp[++pos] = x;
//			}
//			else
//			{
//				int l = 1, r = pos;
//				while (l < r)
//				{
//					int mid = (l + r) / 2;
//					if (dp[mid] >= x) r = mid;
//					else l = mid + 1;
//				}
//				dp[l] = x;
//			}
//		}
//		return pos;
//	}
//};



//typedef long long LL;
//bool isprim(LL x)
//{
//	if (x < 2) return false;
//	for (int i = 2; i <= sqrt(x); i++)
//	{
//		if (x % i == 0) return false;
//	}
//	return true;
//}
//int main()
//{
//	int t;
//	cin >> t;
//	while (t--)
//	{
//		LL a, b;
//		cin >> a >> b;
//		if ((a == 1 && isprim(b)) || (b == 1 && isprim(a)))
//		{
//			cout << "YES" << endl;
//		}
//		else
//		{
//			cout << "NO" << endl;
//		}
//	}
//
//	return 0;
//}


//const int N = 2e5 + 10;
//int n, k;
//int arr[N];
//int main()
//{
//	cin >> n >> k;
//	for (int i = 0; i < n; i++) cin >> arr[i];
//	sort(arr, arr + n);
//	int left = 0, right = 0, ret = 1;
//	while (right < n)
//	{
//		while (arr[right] - arr[left] > k)
//		{
//			left++;
//		}
//		ret = max(ret, right - left + 1);
//		right++;
//	}
//	cout << ret << endl;
//	return 0;
//}



const int N = 1010;
int n, m;
char s1[N];
char s2[N];
int dp[N][N];
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s1[i];
	for (int i = 1; i <= m; i++) cin >> s2[i];
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (s1[i] == s2[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
			else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	}
	cout << dp[n][m] << endl;
	return 0;
}